package com.bblocks.cacheTest.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.CacheKeyPrefix;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
    /**
     * 缓存key添加部分（主要尝试下kryo ，数据单独添加再kryo下）
     */
    private static final String SYSTEMCACHE_REDIS_KEY_ADD = "kryo2:";

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory
            , Jackson2JsonRedisSerializer redisSerializer
    ) {
        RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        RedisCacheManager manager =  new RedisCacheManager(
		            RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),

                this.getRedisCacheConfigurationWithTtl(10,redisSerializer), //
                this.getRedisCacheConfigurationMap(redisSerializer) // 指定 key 策略
        );
        return manager;
    }

    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds,RedisSerializer redisSerializer) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(seconds))
                // 设置key的序列化方式
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                // 设置value的序列化方式
                .serializeValuesWith(RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(redisSerializer)
                )
                ;
        return config;
    }

    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap(RedisSerializer redisSerializer) {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
       // redisCacheConfigurationMap.put("SysArea", this.getRedisCacheConfigurationWithTtl(24*60*60));//1天
        return redisCacheConfigurationMap;
    }

    // key键序列化方式
    @Bean
    public RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }


	@Bean
	public Jackson2JsonRedisSerializer jackson2JsonRedisSerializer(){
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = null;//默认的
		jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);


        /*ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);*/
        jackson2JsonRedisSerializer.setObjectMapper(om);

		return  jackson2JsonRedisSerializer;
	}

    //@Bean
    public CacheKeyPrefix cacheKeyPrefix() {
        return new CacheKeyPrefix() {
            @Override
            public String compute(String cacheName) {
                StringBuilder sBuilder = new StringBuilder(100);
                //sBuilder.append(SYSTEMCACHE_REDIS_KEY_PREFIX).append(":");
                sBuilder.append(cacheName).append(":").append(SYSTEMCACHE_REDIS_KEY_ADD).append(":");
                return sBuilder.toString();
            }
        };
    }



}
